import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import {
  IsArray,
  IsEnum,
  IsNotEmpty,
  IsOptional,
  IsString,
  ValidateNested,
} from 'class-validator';
import { Type } from 'class-transformer';

/**
 * 基础内容类型接口
 */
export interface BaseContent {
  /**
   * 内容类型
   */
  type: string;
}

/**
 * 文本内容类型
 */
export interface TextContent extends BaseContent {
  type: 'text';

  /**
   * 文本内容
   */
  text: string;
}

/**
 * 图片源类型接口
 */
export interface IImageSource {
  /**
   * 图片源类型，目前支持 'url'
   */
  type: 'url';

  /**
   * 图片URL地址
   */
  url: string;
}

/**
 * 图片内容类型
 */
export interface ImageContent extends BaseContent {
  type: 'image';

  /**
   * 图片源信息
   */
  source: IImageSource;
}

/**
 * 消息内容类型（文本或图片）
 */
export type MessageContent = TextContent | ImageContent;

// 多模态消息
export class MultimodalMessageDto {
  @ApiProperty({
    description: '消息角色',
    enum: ['user', 'assistant', 'system'],
    example: 'user',
  })
  @IsEnum(['user', 'assistant', 'system'])
  role: string;

  @ApiProperty({
    description: '消息内容，可以是字符串或内容块数组',
    oneOf: [{ type: 'string' }, { type: 'array', items: { type: 'object' } }],
    example: [
      {
        type: 'text',
        text: '请分析这张图片',
      },
      {
        type: 'image',
        source: {
          type: 'url',
          url: 'https://example.com/image.jpg',
        },
      },
    ],
  })
  content: string | (TextContentBlockDto | ImageContentBlockDto)[];
}

/**
 * 多模态消息请求DTO
 * 扩展自基础完成请求DTO，支持包含文本和图片的消息
 */
export class MultimodalCompletionRequestDto {
  /**
   * 模型名称
   */
  @ApiPropertyOptional({
    description: '使用的AI模型',
    example: 'claude-3-7-sonnet-20250219',
  })
  @IsOptional()
  @IsString()
  model?: string;

  /**
   * 最大生成令牌数
   */
  @ApiProperty({
    description: '生成响应的最大token数',
    example: 1024,
    default: 1024,
  })
  @IsOptional()
  max_tokens?: number;

  /**
   * 消息数组，包含角色和内容
   */
  @ApiProperty({
    description: '消息列表',
    type: [MultimodalMessageDto],
  })
  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => MultimodalMessageDto)
  messages: MultimodalMessageDto[];

  /**
   * 温度参数，控制生成的随机性
   */
  @ApiPropertyOptional({
    description: '温度参数，控制随机性',
    example: 0.7,
    default: 1.0,
    minimum: 0,
    maximum: 1,
  })
  @IsOptional()
  temperature?: number;

  /**
   * 停止序列，用于结束生成
   */
  @ApiPropertyOptional({
    description: '停止生成的序列',
    type: [String],
    example: ['\n', '用户:'],
  })
  @IsOptional()
  @IsArray()
  @IsString({ each: true })
  stop_sequences?: string[];
}

// 定义多模态内容块接口
interface ContentBlock {
  type: string;
  [key: string]: any;
}

// 文本内容块DTO
export class TextContentBlockDto implements ContentBlock {
  @ApiProperty({
    description: '内容类型，固定为"text"',
    enum: ['text'],
    example: 'text',
  })
  @IsEnum(['text'])
  type: 'text';

  @ApiProperty({
    description: '文本内容',
    example: '请分析这张图片中的内容',
  })
  @IsString()
  @IsNotEmpty()
  text: string;
}

// 图片来源DTO
export class ImageSourceDto {
  @ApiProperty({
    description: '图片来源类型',
    enum: ['url', 'base64'],
    example: 'url',
  })
  @IsEnum(['url', 'base64'])
  type: 'url' | 'base64';

  @ApiProperty({
    description: '图片URL地址',
    example: 'https://example.com/image.jpg',
  })
  @IsString()
  @IsNotEmpty()
  url: string;

  @ApiPropertyOptional({
    description: 'Base64编码的图片数据',
    example: '...',
  })
  @IsOptional()
  @IsString()
  data?: string;

  @ApiPropertyOptional({
    description: '图片MIME类型，如"image/jpeg"，仅在type为base64时需要',
    example: 'image/jpeg',
    enum: ['image/jpeg', 'image/png', 'image/gif', 'image/webp'],
  })
  @IsOptional()
  @IsEnum(['image/jpeg', 'image/png', 'image/gif', 'image/webp'])
  media_type?: 'image/jpeg' | 'image/png' | 'image/gif' | 'image/webp';
}

// 图片内容块DTO
export class ImageContentBlockDto implements ContentBlock {
  @ApiProperty({
    description: '内容类型，固定为"image"',
    enum: ['image'],
    example: 'image',
  })
  @IsEnum(['image'])
  type: 'image';

  @ApiProperty({
    description: '图片来源信息',
    type: ImageSourceDto,
  })
  @ValidateNested()
  @Type(() => ImageSourceDto)
  source: ImageSourceDto;
}
